/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package mapcontrol.maplisteners;

import imgparser.ImgFileBag;
import imgparser.SubDivision;
import imgparser.labels.Label;
import java.awt.Point;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.List;
import mapcontrol.ImgConstants;
import mapcontrol.MapConfig;
import mapcontrol.searchmap.FindObjectByPositionListener;

/**
 *
 * @author Pieter
 */
public class Segmentor implements MapListener {
    
    private final MapListener next;
    private List<Point> crossPoints = new ArrayList<Point>();
    private List<Point> otherPoints = new ArrayList<Point>();
    private List<Segment> lines = new ArrayList<Segment>();
    private List<Segment> segments = new ArrayList<Segment>();
    //TODO PIETER remove config
    private MapConfig config;
    
    public Segmentor(MapConfig config, MapListener next) {
        this.config = config;
         this.next = next;
    }


    @Override
    public void addPoint(int type, int subType, int longitude, int latitude, Label label, boolean indexed) {
    }

    @Override
    public void addPoly(int type, int[] longitudes, int[] latitudes, int nbPoints, Label label, boolean line, boolean direction) {
        if (line) {
            crossPoints.add(new Point(longitudes[0], latitudes[0]));
            crossPoints.add(new Point(longitudes[nbPoints - 1], latitudes[nbPoints - 1]));           
            lines.add(new Segment(type, longitudes, latitudes, nbPoints, label, direction));   
            
            for (int i = 1; i < nbPoints-1; i++) {
            Point point = new Point(longitudes[i], latitudes[i]);
            if(otherPoints.contains(point)){
                otherPoints.remove(point);
                crossPoints.add(point);
            }else{
                otherPoints.add(point);
            }
            
        }
        } 
        
    }

    @Override
    public void startMap(ImgFileBag file) {
        next.startMap(file);
    }

    @Override
    public void startSubDivision(SubDivision subDivision) {
        next.startSubDivision(subDivision);
    }

    @Override
    public void finishPainting() {
        segments = SplitSegments(lines, crossPoints);
        
        for (Segment segment : segments) {
            int[] longitudes = segment.getLongitudes();
            int[] latitudes = segment.getLatitudes();
            
            //TODO PIETER add segment type to imgconstans
             next.addPoly(ImgConstants.SELECTED_LINE, longitudes, latitudes, longitudes.length, segment.getLabel(), true, segment.isDirection());
                               
        }
        ///////////////////////////////////////////
        
        List<Polygon> selectedLines = new ArrayList<Polygon>();
        for (Segment segment : segments) {
           selectedLines.add(new Polygon(segment.getLongitudes(),  segment.getLatitudes(), segment.getLongitudes().length));
        }
        /////////////////////////////////////////
               
        
        config.setSelected2Lines(selectedLines);
        config.setCrossPoints(crossPoints);
        next.finishPainting();
    }  

    private List<Segment> SplitSegments(List<Segment> segments, List<Point> crossPoints) {
        List<Segment> ret = new ArrayList<Segment>();
        for (Segment segment : segments) {            
            for (int i = 1; i < segment.getPoints().size() - 1; i++) {
                if (crossPoints.contains(segment.getPoints().get(i))) {
                    ret.add(new Segment(segment.getType(), segment.getPoints().subList(0, i + 1), segment.getLabel(),segment.isDirection()));
                    segment.setPoints(segment.getPoints().subList(i, segment.getPoints().size()));
                    i = 0;
                }
            }
            ret.add(segment);
        }
        return ret;
    }

    private class Segment {

        int type;
        List<Point> points = new ArrayList<Point>();
        Label label;
        boolean direction;

        public Segment(int type, int[] longitudes, int[] latitudes, int nbPoints, Label label, boolean direction) {
            this.type = type;
            this.label = label;
            for (int i = 0; i < nbPoints; i++) {
                points.add(new Point(longitudes[i], latitudes[i]));
            }
            this.direction = direction;
        }

        public Segment(int type, List<Point> points, Label label, boolean direction) {
            this.type = type;
            this.label = label;
            this.points = points;
            this.direction = direction;
        }

        public boolean isDirection() {
            return direction;
        }

        public void setDirection(boolean direction) {
            this.direction = direction;
        }

        
        public Label getLabel() {
            return label;
        }

        public void setLabel(Label label) {
            this.label = label;
        }

        public List<Point> getPoints() {
            return points;
        }

        public void setPoints(List<Point> points) {
            this.points = points;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public int[] getLongitudes() {
            int[] ret = new int[points.size()];
            for (int i = 0; i < points.size(); i++) {
                ret[i] = points.get(i).x;
            }
            return ret;
        }

        public int[] getLatitudes() {
            int[] ret = new int[points.size()];
            for (int i = 0; i < points.size(); i++) {
                ret[i] = points.get(i).y;
            }
            return ret;
        }
    }
}
